(本篇文章網誌版:http://shineright.blogspot.tw/2016/12/day-24.html)
音效及背景音樂可說是現代數位遊戲的靈魂。今天我將為遊戲加入音效與背景音樂。
在Unity為遊戲加入音樂非常簡單。只要為Game Object加入Audio Source Component,並把要播的音樂拉至Audio Clip欄,該Game Object就會發出聲音。然而,只有發出聲音的Game Object還不夠,在Scene中,還需要有一個含有Audio Listener Component的Game Object來接收聲音,音樂才會正常播放。在每個Scene中,Unity會自動為Main Camera加上Audio Listener Component,所以除非想以別的Game Object接收聲音,不然不必另做設定。
了解Unity引擎如何處理聲音後,首先來為遊戲加上最簡單的背景音樂。
到Start Scene新增一個Game Object,命名為「Background Music」,並為它加上Audio Source Component。把要播放的音樂拉到Audio Source Component的Audio Clip欄,並勾選Play On Awake(Game Object Awake時播放)和Loop(重複播放),進入Play Mode,背景音樂就會正常播放了。
遊戲場景的背景音樂作法也相同。但有兩個地方我想修改一下。第一,我希望按下暫停鈕,背景音樂也會跟著一起暫停。第二,我希望進入遊戲結束畫面時,可以降低背景音樂的音調(pitch),讓玩家有遊戲結束的感覺。
這兩點都可用Script輕鬆解決。但首先需把Background Music Game Object的Tag改成「Background Music」,這樣才能在Script中以FindGameObjectWithTag()
輕鬆找到。
開一個新的C# Script,取名為「PauseBackgroundMusicOnCanvas.cs」:
public class PauseBackgroundMusicOnCanvas : MonoBehaviour
{
//儲存背景音樂的AudioSource Component
private AudioSource bgMusicAudioSource;
void OnEnable()
{
//在所有Game Object中找尋Background Music
bgMusicAudioSource = GameObject.FindGameObjectWithTag ("Background Music").GetComponent<AudioSource> ();
//暫停音樂
bgMusicAudioSource.Pause ();
}
void OnDisable()
{
//繼續音樂
bgMusicAudioSource.UnPause ();
}
}
這段程式碼相當簡單。我宣告了一個AudioSource
型態的變數,用以儲存背景音樂的Audio Source Component,這樣就只需呼叫一次耗費時間的GameObject.FindGameObjectWithTag()
函數。
Unity的AudioSource
內建Pause()
和UnPause()
函數,所以其實根本不用多寫什麼複雜程式碼就可以讓音樂暫停了。
把這段Script加到Pause Canvas的Prefab上,之後遊戲暫停時,背景音樂也會跟著暫停了。
接著,再建立一段更簡單的Script。
public class ChangeBackgroundMusicPitchOnStart : MonoBehaviour
{
public float pitch; //寫改成的pitch值
void Start()
{
//取得背景音樂
AudioSource source = GameObject.FindGameObjectWithTag ("Background Music").GetComponent<AudioSource> ();
source.Stop(); //暫停音樂
source.pitch = pitch; //改變pitch
source.Play(); //開始音樂
}
}
把這段Script加到Game Over Canvas的Prefab上,並設定好要改成的pitch值(大約0.5~0.7之間效果不錯,正常值為1)。進入遊戲結束畫面時,背景音樂就變得低沉且緩慢了。
搞定背景音樂後,來為遊戲加入音效吧!
音效比背景音樂還複雜一些。最直覺的做法是,把所有需要音效的Game Object都加上Audio Source Component,並勾選Play On Awake,如此該Game Object產生時就會自動發出聲音了。然而,這種做法有個致命的缺點,那就是Audio Source Component和其他Component一樣,會和擁有它們的Game Object共存亡。
舉個例子,如果把Audio Source Component加在子彈上,當主角的子彈發射時,就會發出聲音。但是,如果子彈在聲音還沒播完成就碰觸到敵子彈或敵人,音效就會隨著Game Object一起被移除,以致於播出的音效只有一半。
於是,我習慣把所有音效都包裝在一個空的Game Object Prefab內,並修改每一段要發出音效的Script,增加一行Instantiate聲音Prefab的程式碼。此外,這個擁有音效的Game Object還得加上Destroy After Seconds (Script) Component,不然時間一久,Scene上就會聚集一堆空的Game Object。
這篇文章我只示範發射子彈的音效,因為其他音效的做法一模一樣。
在Scene中新增一個Game Object,命名為「Blue Ball Audio」,並為它新增Audio Source和Destroy After Seconds (Script) Component。指定好Audio Clip、調好Volume和幾秒後要Destroy後,便可把這個Game Object拉到Project欄做成Prefab。
完成音效Prefab後,到SpawnBullet.cs增加一行變數宣告:
public GameObject shootAudio = null;
以及在GameObject bullet = (Instantiate(…) as GameObject);
這行產生子彈的下方加入產生音效的程式碼:
if (shootAudio != null)
Instantiate (shootAudio, Vector2.zero, Quaternion.identity);
因為不是每個武器射子彈都有聲音,所以我先檢查有沒有shootAudio
,如果有的話(shootAudio != null
),才產生音效。
回到裝備的Prefab,把剛做好的音效Prefab拉到Shoot Audio欄,射子彈的音效就完成了!
待續。